package cyx.web.service;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;

import java.io.File;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class GitPath implements ILocalPath {

    private Set path = new HashSet<>();

    public GitPath(){}

    public GitPath(String gitPath, int fromIndex, int toIndex) {
        try (Repository repository = this.getRepository(gitPath)) {
            String fromLevel = "^";
            String toLevel = "^";
            for (int i = 0; i < fromIndex; i++) {
                fromLevel += "^";
            }
            for (int i = 0; i < toIndex; i++) {
                toLevel += "^";
            }
            ObjectId head = repository.resolve("HEAD" + fromLevel + "{tree}");
            ObjectId oldHead = repository.resolve("HEAD" + toLevel + "{tree}");
            try (ObjectReader reader = repository.newObjectReader()) {

                CanonicalTreeParser oldTreeIter = new CanonicalTreeParser();
                oldTreeIter.reset(reader, oldHead);

                CanonicalTreeParser newTreeIter = new CanonicalTreeParser();
                newTreeIter.reset(reader, head);

                try (Git git = new Git(repository)) {

                    List<DiffEntry> diffs = git.diff()
                            .setNewTree(newTreeIter)
                            .setOldTree(oldTreeIter)
                            .call();

                    for (DiffEntry entry : diffs) {
                        String strPath = "";
                        switch (entry.getChangeType()) {
                            case ADD:
                                strPath = entry.getNewPath().trim();
                               // buf.append(newPath);
                                break;
                            case COPY:
                                strPath = entry.getNewPath().trim();
                               // buf.append(oldPath + "->" + newPath);
                                break;
                            case DELETE:
                                strPath = entry.getOldPath().trim();
                               // buf.append(oldPath);
                                break;
                            case MODIFY:
                                strPath = entry.getOldPath().trim();
                               // buf.append(oldPath);
                                break;
                            case RENAME:
                                strPath = entry.getNewPath().trim();
                               // buf.append(oldPath + "->" + newPath);
                                break;
                        }

                        path.add(strPath.replace(".../", ""));
                    }
                } catch (GitAPIException e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Repository getRepository(String gitPath) throws IOException {
        return new FileRepositoryBuilder()
                .setGitDir(new File(gitPath)).build();
    }

    @Override
    public Set getPath() {
        return this.path;
    }

    @Override
    public void addPath(String path) {

    }

    @Override
    public void savePath() {

    }

}
